<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        /* 
        1. 分支切换如何进行优化
        2. 
        */
        const data = { ok: true, text: '123' }
        let activeAffect // 这个是全局变量 存储副作用函数
        let bucket = new WeakMap()
        let obj = new Proxy(data, {
            get(target, key) {
                debugger
                track(target, key)
                console.log('访问了', target[key]);
                return target[key]
            },
            set(target, key, newVal) {
                debugger
                target[key] = newVal
                console.log('修改了', target[key], '为', newVal);
                trigger(target, key)
            }
        })
        function track(target, key) {
            debugger
            if (!activeAffect) {
                return target[key]
            }
            let depMap = bucket.get(target)
            if (!depMap) {
                bucket.set(target, (depMap = new Map()))
            }
            let depSet = depMap.get(key)
            if (!depSet) {
                depMap.set(key, (depSet = new Set()))
            }
            // depSet就是专门用来收集副作用域函数的集合
            debugger
            depSet.add(activeAffect)
            // deps就是与副作用函数存在联系的依赖集合
            // 把它添加到activeEffect.deps的数组中
            activeAffect.deps.push(depSet)
        }
        function trigger(target, key) {
            debugger
            let depMap = bucket.get(target)
            let effects = depMap.get(key)
            effects && effects.forEach(fn => fn())
        }
        function effect(fn) {
            debugger
            const effectFn = () => {
                debugger
                // 清除所有effectFn里面的deps的依赖集合
                cleanUp(effectFn)
                activeAffect = effectFn
                fn()
            }
            // 用于收集所有和这个副作用函数有关的集合
            effectFn.deps = []
            // 执行副作用函数
            effectFn()
        }
        effect(() => {
            console.log(1); //1
            debugger
            // 我们怎么去测试这个效果呢？我们把 obj.ok = false;然后 obj.text = '45' 改他个很多很多次。发现这里还是会被触发很多次。即便这里的document.body.innerHTML的值不需要改变
            document.querySelector('body').innerHTML = obj.ok ? obj.text : 'not'
        })
        function cleanUp(effectFn) {
            debugger
            for (let i = 0; i < effectFn.deps.length; i++) {
                // deps是依赖集合
                const deps = effectFn.deps[i]
                // 将effectFn从依赖集合中删除
                deps.delete(effectFn)
            }
            // 重置deps数组
            effectFn.deps.length = 0
        }

        // 执行的顺序是怎么样的呢？
        // 1. 先修改 obj.text = '123'
        // 2. 然后触发set 更新值
        // 3. 触发trigger 取出副作用域函数 执行它
        // 4. 执行副作用函数之前 找到所有的副作用函数的集合，清空，
        // 5. 再执行当前传入的副作用函数
        // 6. 又添加到set结构中去 此时对于副作用函数集合的遍历仍然存在




    </script>
</body>

</html>